﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Slam;
using Microsoft.SharePoint;
using Slam.Configuration;
using Slam.Logging;
using Slam.Data;
using Slam.SharePoint;
using Slam.Events;
using System.Xml.Linq;
using System.Collections;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using SlamCms.SharePoint.Tagging.FieldTypes;
using SlamCms.SharePoint.SlamProfiles.ContentItem.Data;
using SlamCms.SharePoint.SlamProfiles.ContentItem.Services;
using SlamCms.SharePoint.Tagging.Services;
using System.Text.RegularExpressions;

namespace SlamCms.SharePoint.SlamProfiles.ContentItem
{
	public class ContentItemContentTypeItemUpdater : ContentTypeItemUpdater
	{
		private IConfigurationManager _configuration;
		private IDataServices _dataServices;
		private DataService _dataService;
		private ILogger _logger;
		private string _dataSchema;

		#region Constructors

		public ContentItemContentTypeItemUpdater(IDataServices dataServices, IConfigurationManager configuration, ILogger logger)
			: base(dataServices, configuration, logger)
		{
			_configuration = configuration;
			_dataServices = dataServices;
			_dataSchema = ((XmlSqlDataMapping)configuration.DataMapping).GetDataSchema();
			_dataService = new DataService(configuration.GetSection<ConnectionStringSection>("ConnectionStrings").Default);
			_logger = logger;

			_configuration.RegisterSection("ContentItem",
				config =>
				{
					object section = null;
					if (config is XDocument)
					{
						section = new ContentItemProfileSection((XDocument)config);
					}
					return section;
				});
		}

		#endregion

		public override bool Update(SPListItem listItem)
		{
			SPList list = listItem.ParentList;

			string previousStatus = listItem.GetPublishingStatus();
			string previousContentTypeId = listItem.GetSlamPropertyValue("PreviousContentTypeId");
			string contentTypeId = listItem.ContentTypeId.ToString();

			bool listIsVersioned = list.EnableModeration && list.EnableVersioning;
			bool contentTypeChange = !String.IsNullOrEmpty(previousContentTypeId) && list.ContentTypes.Cast<SPContentType>().Any(c => c.Id.ToString() == previousContentTypeId) && !previousContentTypeId.Equals(contentTypeId, StringComparison.OrdinalIgnoreCase);

			string slamItemContextTypeName = SlamItemContext.TypeName;
			if (listIsVersioned)
			{
				listItem.SetPublishingStatus();
				if (list.BaseTemplate == SPListTemplateType.DocumentLibrary)
				{
					Thread.Sleep(500);
				}
				string status = listItem.GetPublishingStatus();
				if (status.Equals(ContentItemStatus.Live.Name, StringComparison.OrdinalIgnoreCase) && listItem.HasPublishedVersion && listItem.GetLiveVersionId() != 0)
				{
					previousContentTypeId = listItem.Versions.GetVersionFromID(listItem.GetLiveVersionId())["ContentTypeId"].ToString();
					contentTypeChange = !String.IsNullOrEmpty(previousContentTypeId) && !previousContentTypeId.Equals(contentTypeId, StringComparison.OrdinalIgnoreCase);
				}

				if (!contentTypeChange && status.Equals(ContentItemStatus.Live.Name, StringComparison.OrdinalIgnoreCase) &&
					(previousStatus.Equals(ContentItemStatus.Modified.Name, StringComparison.OrdinalIgnoreCase) ||
					 previousStatus.Equals(ContentItemStatus.PendingApprovalModified.Name, StringComparison.OrdinalIgnoreCase)))
				{
					listItem.SetSlamProperty("PreviousContentTypeId", listItem.ContentTypeId.ToString());
					listItem.SystemUpdate(false);
					ContentItemEvents.Delete(listItem, _dataServices, _configuration, _logger, _dataService, _dataSchema, "Delete CT");
					previousStatus = listItem.GetPublishingStatus();
				}
				else if (contentTypeChange && status.Equals(ContentItemStatus.Live.Name, StringComparison.OrdinalIgnoreCase))
				{
					listItem.SetSlamProperty("PreviousContentTypeId", listItem.ContentTypeId.ToString());
					listItem.SystemUpdate(false);
					ContentItemEvents.Delete(listItem, _dataServices, _configuration, _logger, _dataService, _dataSchema, "Delete CT");
					listItem["SLAM ID"] = Regex.Replace(Convert.ToString(listItem.GetUniqueId()), "-p", "");
					SlamItemContext.TypeName = list.ContentTypes[new SPContentTypeId(previousContentTypeId)].Parent.Name;
					ContentItemEvents.Delete(listItem, _dataServices, _configuration, _logger, _dataService, _dataSchema, "Delete CT");
					SlamItemContext.TypeName = slamItemContextTypeName;
					previousStatus = listItem.GetPublishingStatus();
				}
				else if (contentTypeChange &&
					(status.Equals(ContentItemStatus.New.Name, StringComparison.OrdinalIgnoreCase) ||
					status.Equals(ContentItemStatus.Modified.Name, StringComparison.OrdinalIgnoreCase) ||
					status.Equals(ContentItemStatus.PendingApprovalModified.Name, StringComparison.OrdinalIgnoreCase)) &&
					(previousStatus.Equals(ContentItemStatus.New.Name, StringComparison.OrdinalIgnoreCase) ||
					previousStatus.Equals(ContentItemStatus.Modified.Name, StringComparison.OrdinalIgnoreCase) ||
					previousStatus.Equals(ContentItemStatus.PendingApprovalModified.Name, StringComparison.OrdinalIgnoreCase)))
				{
					SlamItemContext.TypeName = list.ContentTypes[new SPContentTypeId(previousContentTypeId)].Parent.Name;
					ContentItemEvents.Delete(listItem, _dataServices, _configuration, _logger, _dataService, _dataSchema, "Delete CT");
					previousStatus = listItem.GetPublishingStatus();
				}
			}
			else if (contentTypeChange)
			{
				SlamItemContext.TypeName = list.ContentTypes[new SPContentTypeId(previousContentTypeId)].Parent.Name;
				listItem.SetSlamProperty("PreviousContentTypeId", listItem.ContentTypeId.ToString());
				listItem.SystemUpdate(false);
				ContentItemEvents.Delete(listItem, _dataServices, _configuration, _logger, _dataService, _dataSchema, "Delete CT");
			}

			SlamItemContext.TypeName = slamItemContextTypeName;
			if (String.IsNullOrEmpty(previousStatus))
			{
				listItem.SetPublishingStatus();
			}
			return ContentItemEvents.Update(listItem, _dataServices, _configuration, _logger, _dataService, _dataSchema, "Update CT", true);
		}
	}
}
